package com.tyut.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch.core.DeleteResponse;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tyut.domain.MusicDocument;
import com.tyut.domain.TagDocument;
import com.tyut.domain.UserDocument;
import com.tyut.domain.dto.SearchRequest;
import com.tyut.domain.vo.SearchResult;
import com.tyut.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 搜索服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SearchServiceImpl implements SearchService {

    private final ElasticsearchClient elasticsearchClient;
    private final ObjectMapper objectMapper;

    @Override
    public SearchResult<MusicDocument> searchMusic(SearchRequest request) {
        try {
            // 构建搜索请求
            co.elastic.clients.elasticsearch.core.SearchRequest.Builder searchRequest = new co.elastic.clients.elasticsearch.core.SearchRequest.Builder();
            searchRequest.index("music");
            
            // 构建查询条件
            if (StringUtils.hasText(request.getKeyword())) {
                searchRequest.query(q -> q
                    .bool(b -> {
                        b.should(s -> s.match(m -> m.field("title").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("description").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("tags").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("artist").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("album").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("creatorName").query(request.getKeyword())));
                        
                        // 只搜索已发布的音乐
                        b.must(m -> m.term(t -> t.field("status").value(1)));
                        
                        return b;
                    })
                );
            } else {
                searchRequest.query(q -> q
                    .bool(b -> b.must(m -> m.term(t -> t.field("status").value(1))))
                );
            }
            
            // 设置分页
            int from = (request.getPageNum() - 1) * request.getPageSize();
            searchRequest.from(from);
            searchRequest.size(request.getPageSize());
            
            // 设置排序
            if (StringUtils.hasText(request.getOrderBy())) {
                String sortOrderStr = "asc".equals(request.getOrderType()) ? "asc" : "desc";
                SortOrder sortOrder = "asc".equals(sortOrderStr) ? SortOrder.Asc : SortOrder.Desc;
                searchRequest.sort(s -> s.field(f -> f.field(request.getOrderBy()).order(sortOrder)));
            } else {
                // 默认按相关度排序
                searchRequest.sort(s -> s.field(f -> f.field("_score").order(SortOrder.Desc)));
            }
            
            // 执行搜索
            SearchResponse<MusicDocument> searchResponse = elasticsearchClient.search(
                searchRequest.build(),
                MusicDocument.class
            );
            
            // 解析结果
            SearchResult<MusicDocument> result = new SearchResult<>();
            result.setTotal(searchResponse.hits().total().value());
            result.setTook(searchResponse.took());
            result.setPageNum(request.getPageNum());
            result.setPageSize(request.getPageSize());
            
            // 计算总页数
            long totalPages = (result.getTotal() + request.getPageSize() - 1) / request.getPageSize();
            result.setPages(totalPages);
            result.setHasNext(request.getPageNum() < totalPages);
            
            // 解析搜索结果
            List<MusicDocument> musicList = new ArrayList<>();
            for (Hit<MusicDocument> hit : searchResponse.hits().hits()) {
                MusicDocument music = hit.source();
                if (music != null) {
                    music.setId(hit.id());
                    musicList.add(music);
                }
            }
            result.setList(musicList);
            
            return result;
        } catch (IOException e) {
            log.error("搜索音乐异常", e);
            return new SearchResult<>();
        }
    }

    @Override
    public SearchResult<UserDocument> searchUser(SearchRequest request) {
        try {
            // 构建搜索请求
            co.elastic.clients.elasticsearch.core.SearchRequest.Builder searchRequest = new co.elastic.clients.elasticsearch.core.SearchRequest.Builder();
            searchRequest.index("user");
            
            // 构建查询条件
            if (StringUtils.hasText(request.getKeyword())) {
                searchRequest.query(q -> q
                    .bool(b -> {
                        b.should(s -> s.match(m -> m.field("username").query(request.getKeyword())));
                        b.should(s -> s.term(t -> t.field("email").value(request.getKeyword())));
                        
                        // 只搜索正常状态的用户
                        b.must(m -> m.term(t -> t.field("status").value(0)));
                        
                        return b;
                    })
                );
            } else {
                searchRequest.query(q -> q
                    .bool(b -> b.must(m -> m.term(t -> t.field("status").value(0))))
                );
            }
            
            // 设置分页
            int from = (request.getPageNum() - 1) * request.getPageSize();
            searchRequest.from(from);
            searchRequest.size(request.getPageSize());
            
            // 设置排序
            if (StringUtils.hasText(request.getOrderBy())) {
                String sortOrderStr = "asc".equals(request.getOrderType()) ? "asc" : "desc";
                SortOrder sortOrder = "asc".equals(sortOrderStr) ? SortOrder.Asc : SortOrder.Desc;
                searchRequest.sort(s -> s.field(f -> f.field(request.getOrderBy()).order(sortOrder)));
            } else {
                // 默认按相关度排序
                searchRequest.sort(s -> s.field(f -> f.field("_score").order(SortOrder.Desc)));
            }
            
            // 执行搜索
            SearchResponse<UserDocument> searchResponse = elasticsearchClient.search(
                searchRequest.build(),
                UserDocument.class
            );
            
            // 解析结果
            SearchResult<UserDocument> result = new SearchResult<>();
            result.setTotal(searchResponse.hits().total().value());
            result.setTook(searchResponse.took());
            result.setPageNum(request.getPageNum());
            result.setPageSize(request.getPageSize());
            
            // 计算总页数
            long totalPages = (result.getTotal() + request.getPageSize() - 1) / request.getPageSize();
            result.setPages(totalPages);
            result.setHasNext(request.getPageNum() < totalPages);
            
            // 解析搜索结果
            List<UserDocument> userList = new ArrayList<>();
            for (Hit<UserDocument> hit : searchResponse.hits().hits()) {
                UserDocument user = hit.source();
                if (user != null) {
                    user.setId(Long.valueOf(hit.id()));
                    userList.add(user);
                }
            }
            result.setList(userList);
            
            return result;
        } catch (IOException e) {
            log.error("搜索用户异常", e);
            return new SearchResult<>();
        }
    }

    @Override
    public SearchResult<TagDocument> searchTag(SearchRequest request) {
        try {
            // 构建搜索请求
            co.elastic.clients.elasticsearch.core.SearchRequest.Builder searchRequest = new co.elastic.clients.elasticsearch.core.SearchRequest.Builder();
            searchRequest.index("tag");
            
            // 构建查询条件
            if (StringUtils.hasText(request.getKeyword())) {
                searchRequest.query(q -> q
                    .bool(b -> {
                        b.should(s -> s.match(m -> m.field("name").query(request.getKeyword())));
                        b.should(s -> s.match(m -> m.field("description").query(request.getKeyword())));
                        return b;
                    })
                );
            }
            
            // 设置分页
            int from = (request.getPageNum() - 1) * request.getPageSize();
            searchRequest.from(from);
            searchRequest.size(request.getPageSize());
            
            // 设置排序
            if (StringUtils.hasText(request.getOrderBy())) {
                String sortOrderStr = "asc".equals(request.getOrderType()) ? "asc" : "desc";
                SortOrder sortOrder = "asc".equals(sortOrderStr) ? SortOrder.Asc : SortOrder.Desc;
                searchRequest.sort(s -> s.field(f -> f.field(request.getOrderBy()).order(sortOrder)));
            } else {
                // 默认按使用次数排序
                searchRequest.sort(s -> s.field(f -> f.field("useCount").order(SortOrder.Desc)));
            }
            
            // 执行搜索
            SearchResponse<TagDocument> searchResponse = elasticsearchClient.search(
                searchRequest.build(),
                TagDocument.class
            );
            
            // 解析结果
            SearchResult<TagDocument> result = new SearchResult<>();
            result.setTotal(searchResponse.hits().total().value());
            result.setTook(searchResponse.took());
            result.setPageNum(request.getPageNum());
            result.setPageSize(request.getPageSize());
            
            // 计算总页数
            long totalPages = (result.getTotal() + request.getPageSize() - 1) / request.getPageSize();
            result.setPages(totalPages);
            result.setHasNext(request.getPageNum() < totalPages);
            
            // 解析搜索结果
            List<TagDocument> tagList = new ArrayList<>();
            for (Hit<TagDocument> hit : searchResponse.hits().hits()) {
                TagDocument tag = hit.source();
                if (tag != null) {
                    tag.setId(hit.id());
                    tagList.add(tag);
                }
            }
            result.setList(tagList);
            
            return result;
        } catch (IOException e) {
            log.error("搜索标签异常", e);
            return new SearchResult<>();
        }
    }

    @Override
    public boolean indexMusic(MusicDocument document) {
        try {
            IndexResponse response = elasticsearchClient.index(i -> i
                .index("music")
                .id(document.getId())
                .document(document)
            );
            return response.result().name().equalsIgnoreCase("Created") || 
                   response.result().name().equalsIgnoreCase("Updated");
        } catch (IOException e) {
            log.error("索引音乐文档异常", e);
            return false;
        }
    }

    @Override
    public boolean indexUser(UserDocument document) {
        try {
            IndexResponse response = elasticsearchClient.index(i -> i
                .index("user")
                .id(document.getId().toString())
                .document(document)
            );
            return response.result().name().equalsIgnoreCase("Created") || 
                   response.result().name().equalsIgnoreCase("Updated");
        } catch (IOException e) {
            log.error("索引用户文档异常", e);
            return false;
        }
    }

    @Override
    public boolean indexTag(TagDocument document) {
        try {
            IndexResponse response = elasticsearchClient.index(i -> i
                .index("tag")
                .id(document.getId())
                .document(document)
            );
            return response.result().name().equalsIgnoreCase("Created") || 
                   response.result().name().equalsIgnoreCase("Updated");
        } catch (IOException e) {
            log.error("索引标签文档异常", e);
            return false;
        }
    }

    @Override
    public boolean deleteMusic(String id) {
        try {
            DeleteResponse response = elasticsearchClient.delete(d -> d
                .index("music")
                .id(id)
            );
            return response.result().name().equalsIgnoreCase("Deleted");
        } catch (IOException e) {
            log.error("删除音乐文档异常", e);
            return false;
        }
    }

    @Override
    public boolean deleteUser(Long id) {
        try {
            DeleteResponse response = elasticsearchClient.delete(d -> d
                .index("user")
                .id(id.toString())
            );
            return response.result().name().equalsIgnoreCase("Deleted");
        } catch (IOException e) {
            log.error("删除用户文档异常", e);
            return false;
        }
    }

    @Override
    public boolean deleteTag(String id) {
        try {
            DeleteResponse response = elasticsearchClient.delete(d -> d
                .index("tag")
                .id(id)
            );
            return response.result().name().equalsIgnoreCase("Deleted");
        } catch (IOException e) {
            log.error("删除标签文档异常", e);
            return false;
        }
    }
} 